package com.lqq.api.impl;

import com.lqq.TransactionStatus;
import com.lqq.api.AccountService;
import com.lqq.dto.AccountDto;
import com.lqq.entity.Account;
import com.lqq.entity.Transaction;
import com.lqq.repository.AccountRepository;
import com.lqq.repository.TransactionRepo;
import lombok.extern.slf4j.Slf4j;
import org.mengyun.tcctransaction.api.Compensable;
import org.mengyun.tcctransaction.dubbo.context.DubboTransactionContextEditor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

/**
 * @author qingqing.liang
 * @create 2018-01-30
 **/
//@Service
@Slf4j
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountRepository accountRepository;
    @Autowired
    private TransactionRepo transactionRepo;

    @Override
    public AccountDto getById(Long id) {
        Account account = accountRepository.findOne(id);
        AccountDto accountDto = new AccountDto();
        BeanUtils.copyProperties(account, accountDto);
        return accountDto;
    }

    @Override
    public void add(AccountDto accountDto) {
        Account account = new Account();
        BeanUtils.copyProperties(accountDto, account);
        accountRepository.save(account);

    }

    @Override
    @Compensable(confirmMethod = "confirmRecord", cancelMethod = "cancelRecord"
            , transactionContextEditor = DubboTransactionContextEditor.class)
    @Transactional(rollbackFor = Exception.class)
    public String record(Long accountId, BigDecimal orderAmount, Long transactionId) {


        if(orderAmount.compareTo(BigDecimal.valueOf(0L)) < 0){
            throw new RuntimeException("订单金额不能小于0" + "当前订单金额是：" +orderAmount);
        }

        Account account = accountRepository.findOne(accountId);
        account.setBalance(account.getBalance().subtract(orderAmount));
        Transaction transaction = new Transaction();
        transaction.setBusinessId(account.getId());
        transaction.setTransactionId(transactionId);
        transaction.setStatus(TransactionStatus.PROCESSING);
        accountRepository.save(account);
        transactionRepo.save(transaction);
        log.info("支付系统tcc事务Try了");
        return "";
    }


    /**
     * 事务表修改为 confirm
     * @param accountId
     * @param orderAmount
     */
    @Transactional(rollbackFor = Exception.class)
    public void confirmRecord(Long accountId, BigDecimal orderAmount, Long transactionId) {

        Transaction transaction = transactionRepo.findTransactionByTransactionId(transactionId);
        if(transaction == null){
            throw new RuntimeException("没有对应的事务" + transactionId);
        }
        //事务已经提交，不做操作
        if(transaction.getStatus() == TransactionStatus.SUCCESS){
            return;
        }else if(transaction.getStatus() == TransactionStatus.PROCESSING){
            transaction.setStatus(TransactionStatus.SUCCESS);

            transactionRepo.save(transaction);

            log.info("支付系统tcc提交事务");
        }else{

            throw new RuntimeException("不是处理中的事务" + transactionId);
        }
    }

    /**
     * 状态改为cancel
     * 	库存 + 1
     * @param accountId
     * @param orderAmount
     */
    @Transactional(rollbackFor = Exception.class)
    public void cancelRecord(Long accountId, BigDecimal orderAmount, Long transactionId) {

        Transaction transaction = transactionRepo.findTransactionByTransactionId(transactionId);
        //没有插入事务/或者事务已经提交/或者事务已经回滚 不需要做任何操作
        if(transaction == null || TransactionStatus.SUCCESS == transaction.getStatus()
                || TransactionStatus.CANCEL == transaction.getStatus() ){
            return;
        }

        Account account = accountRepository.findOne(accountId);
        account.setBalance(account.getBalance().add(orderAmount));
        this.accountRepository.save(account);

        transaction.setStatus(TransactionStatus.CANCEL);
        transactionRepo.save(transaction);

        log.info("支付系统tcc取消事务");
    }

}
